#include <iostream>
using namespace std;

#include "MemoryTracer.h"

#include "delegate/Delegate.h"
#include "delegate/EventHandler.h"
using namespace xgu;

#include "InvokeTest.h"
#include "ArgsBinding.h"

class CFoo
{
public:
	CFoo(int v)
	{
		this->v = v;
	}
	int foo(int a, int b)
	{
		return a + b + v;
	}
private:
	int v;
};

class Poster
{
public:
	EventHandler<EventArgs> SomeEvent;

	void OnSomeEvent()
	{
		SomeEvent(this, EventArgs::Empty);
		cout << endl;
	}
};

class Subscriber
{
public:
	void OnSomeEvent0(void* sender, EventArgs e)
	{
		cout << "OnSomeEvent0" << endl;
	}
	void OnSomeEvent1(void* sender, EventArgs e)
	{
		cout << "OnSomeEvent1" << endl;
	}
	void OnSomeEvent2(void* sender, EventArgs e)
	{
		cout << "OnSomeEvent2" << endl;
	}
};



void DelegateTest()
{
	// Delegate Test

	CFoo ca(0), cb(1), cc(2);

	Delegate<int, int, int> da;
	Delegate<int, int, int> *db = new Delegate<int, int, int>();
	da += Delegate<int, int, int>(ca, &CFoo::foo);
	*db += Delegate<int, int, int>(cb, &CFoo::foo);
	da += *db;
	delete db;
	db = NULL;
	da += Delegate<int, int, int>(&cc, &CFoo::foo);

	cout << da(0, 0)[0] << endl;
	cout << da(0, 0)[1] << endl;
	cout << da(0, 0)[2] << endl;

	Poster poster;
	Subscriber subscriber;

	poster.SomeEvent += EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent0);
	poster.OnSomeEvent();

	poster.SomeEvent += EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent0);
	poster.SomeEvent += EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent1);
	poster.OnSomeEvent();

	poster.SomeEvent -= EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent0);
	poster.SomeEvent += EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent1);
	poster.SomeEvent += EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent2);
	poster.OnSomeEvent();

	poster.SomeEvent -= EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent0);
	poster.SomeEvent -= EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent1);
	poster.SomeEvent += EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent2);
	poster.OnSomeEvent();

	poster.SomeEvent -= EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent0);
	poster.SomeEvent -= EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent1);
	poster.SomeEvent -= EventHandler<EventArgs>::Delegate(subscriber, &Subscriber::OnSomeEvent2);
	poster.OnSomeEvent();
}

int main(int argc, char* argv[])
{
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

	DelegateTest();
	TestArgsBinding();
	InvokeTest();

	return 0;
}

